package com.bang.concurrency.example.atomic;

import com.bang.concurrency.annotations.ThreadSafe;
import lombok.extern.slf4j.Slf4j;

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Semaphore;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * @Auther: Bang
 * @Date: 2019/9/29 22:21
 * @Description: 模拟线程安全 AtomicInteger 底层实现 Cas,使用一个do while死循环去实现
 * 什么是CAS
 * CAS是英文单词CompareAndSwap的缩写，中文意思是：比较并替换。CAS需要有3个操作数：内存地址V，旧的预期值A，即将要更新的目标值B。
 * CAS指令执行时，当且仅当内存地址V的值与预期值A相等时，将内存地址V的值修改为B，否则就什么都不做。整个比较并替换的操作是一个原子操作。
 * CAS的缺点：
 * CAS虽然很高效的解决了原子操作问题，但是CAS仍然存在三大问题。
 * 循环时间长开销很大。
 * 只能保证一个共享变量的原子操作。
 * ABA问题。(使用版本号解决)
 */
@Slf4j
@ThreadSafe
public class AtomicExample1 {

    // 同时并发执行的线程数
    private static int threadCount = 200;

    // 请求总数
    private static int clientCount = 5000;

    private static AtomicInteger count = new AtomicInteger(0);


    public static void main(String[] args) throws InterruptedException {
        ExecutorService executorService = Executors.newCachedThreadPool();
        final Semaphore semaphore = new Semaphore(threadCount);
        CountDownLatch countDownLatch = new CountDownLatch(clientCount);
        for (int index = 0; index < clientCount; index++) {
            executorService.execute(() -> {
                try {
                    semaphore.acquire();
                    add();
                    semaphore.release();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                countDownLatch.countDown();
            });
        }
        countDownLatch.await();
        executorService.shutdown();
        log.error("count = {}", count);
    }

    private static void add() {
        count.getAndIncrement();
    }
}
